﻿using Decal.Adapter;
using Decal.Adapter.Wrappers;
using System;
using System.Media;
using System.Text;


namespace SixthSense
{
    public partial class PluginCore : PluginBase
    {
        ObjectInfo PlayerObject = new ObjectInfo();

        ObjectInfoList _Items = new ObjectInfoList();
        ObjectInfoList _Monsters = new ObjectInfoList();
        ObjectInfoList _Specials = new ObjectInfoList();
        ObjectInfoList _ValueQueue = new ObjectInfoList();
        ObjectInfoList _WorkmanshipQueue = new ObjectInfoList();

        double _RemoveDistance = 0.6;

        private string GetRelativeCoords(ObjectInfo oiCoords)
        {
            CoordsObject coCoords = new CoordsObject(oiCoords.NSCoordinate, oiCoords.EWCoordinate);
            return GetRelativeCoords(coCoords);
        }

        private string GetRelativeCoords(CoordsObject coords)
        {
            string sNS;
            string sEW;
            double fEW = coords.EastWest - PlayerObject.EWCoordinate;
            double fNS = coords.NorthSouth - PlayerObject.NSCoordinate;

            if (fNS >= 10.0 || fNS <= -10.0)
            {
                sNS = string.Format("{0:F1}", Math.Abs(fNS));
            }
            else
            {
                sNS = string.Format("{0:F2}", Math.Abs(fNS));
            }

            if (fNS < 0)
            {
                // negative is south
                sNS += "S";
            }
            else
            {
                sNS += "N";
            }


            if (fEW >= 10.0 || fEW <= -10.0)
            {
                sEW = string.Format("{0:F1}", Math.Abs(fEW));
            }
            else
            {
                sEW = string.Format("{0:F2}", Math.Abs(fEW));
            }

            if (fEW < 0)
            {
                // negative is west
                sEW += "W";
            }
            else
            {
                sEW += "E";
            }

            return sNS + " " + sEW;
        }

        // this should be used when we have a moved object.  That new object info is passed in
        private void UpdateItemLocation(ObjectInfo Obj)
        {
            int index = 0;
            ListRow row;

            foreach (ObjectInfo item in _Items)
            {
                if (item.ID == Obj.ID)
                {
                    item.Landblock = Obj.Landblock;
                    item.NSCoordinate = Obj.NSCoordinate;
                    item.EWCoordinate = Obj.EWCoordinate;

                    if (_Config.CurrentOptions.RelativeCoords)
                    {
                        item.GetRelativeCoords(PlayerObject);
                    }

                    // update the list
                    row = ItemList[index];
                    row[2][0] = item.Coords;

                    break;
                }

                index++;
            }

            index = 0;
            foreach (ObjectInfo item in _Monsters)
            {
                if (item.ID == Obj.ID)
                {
                    item.Landblock = Obj.Landblock;
                    item.NSCoordinate = Obj.NSCoordinate;
                    item.EWCoordinate = Obj.EWCoordinate;

                    if (_Config.CurrentOptions.RelativeCoords)
                    {
                        item.GetRelativeCoords(PlayerObject);
                    }

                    // update the list
                    row = MonsterList[index];
                    row[2][0] = item.Coords;

                    break;
                }

                index++;
            }

            index = 0;
            foreach (ObjectInfo item in _Specials)
            {
                if (item.ID == Obj.ID)
                {
                    item.Landblock = Obj.Landblock;
                    item.NSCoordinate = Obj.NSCoordinate;
                    item.EWCoordinate = Obj.EWCoordinate;

                    if (_Config.CurrentOptions.RelativeCoords)
                    {
                        item.GetRelativeCoords(PlayerObject);
                    }

                    // update the list
                    row = SpecialList[index];
                    row[2][0] = item.Coords;

                    break;
                }

                index++;
            }
        }

        // should only call this when the player has moved
        private bool UpdateItemLocations()
        {
            int index = 0;
            ListRow row;

            foreach (ObjectInfo item in _Items)
            {
                CoordsObject coords = new CoordsObject(item.NSCoordinate, item.EWCoordinate);
                
                if (_Config.CurrentOptions.RelativeCoords)
                {
                    item.GetRelativeCoords(PlayerObject);
                }

                row = ItemList[index];
                row[2][0] = item.Coords;
                index++;
            }

            index = 0;
            foreach (ObjectInfo item in _Monsters)
            {
                CoordsObject coords = new CoordsObject(item.NSCoordinate, item.EWCoordinate);

                if (_Config.CurrentOptions.RelativeCoords)
                {
                    item.GetRelativeCoords(PlayerObject);
                }

                row = MonsterList[index];
                row[2][0] = item.Coords;
                index++;
            }

            index = 0;
            foreach (ObjectInfo item in _Specials)
            {
                CoordsObject coords = new CoordsObject(item.NSCoordinate, item.EWCoordinate);

                if (_Config.CurrentOptions.RelativeCoords)
                {
                    item.GetRelativeCoords(PlayerObject);
                }

                row = SpecialList[index];
                row[2][0] = item.Coords;
                index++;
            }
            
            return true;
        }

        private bool AddItem(ObjectInfo Item)
        {
            WriteToChat("Attempting to add item: " + Item.Name);

            // check if we should be display coords relative to our toon or not, via config options
            if (_Config.CurrentOptions.RelativeCoords)
            {
                Item.GetRelativeCoords(PlayerObject);
            }

            ListRow row;

            switch (Item.Type)
            {
                case "monster":
                    _Monsters.Add(Item);
                    row = MonsterList.Add();
                    Notebook.ActiveTab = 1;
                    break;

                case "special":
                    _Specials.Add(Item);
                    row = SpecialList.Add();
                    Notebook.ActiveTab = 2;
                    break;

                case "item":
                case "loot":
                default:
                    _Items.Add(Item);
                    row = ItemList.Add();
                    Notebook.ActiveTab = 0;
                    break;
            }

            // now add the item to the UI
            row[0][1] = Item.Icon + 0x6000000;
            row[1][0] = Item.Name;
            row[2][0] = Item.Coords;

            if (_Config.CurrentOptions.Popup)
            {
                _MainView.Activate();
            }

            if (_Config.CurrentOptions.ChatWindow)
            {
                StringBuilder s = new StringBuilder();

                if (Item.Material.Name != "")
                {
                    s.Append(Item.Material.Name + " ");
                }

                s.Append(Item.Name + " ");
                s.Append(Item.Coords + " ");
                s.Append(Item.Text);

                WriteToChat(s.ToString());
            }

            return true;
        }

        /*
        private bool AddItem(WorldObject Item, string ItemType)
        {
            CoordsObject coords = Item.Coordinates();
            ObjectInfo info = new ObjectInfo();

            // check if we should be display coords relative to our toon or not, via config options
            if (_Config.CurrentOptions.RelativeCoords)
            {
                info.GetRelativeCoords(PlayerObject);
            }

            // update the internal item tracking before first
            info.ID = Item.Id;
            info.NSCoordinate = coords.NorthSouth;
            info.EWCoordinate = coords.EastWest;

            ListRow row;

            switch (ItemType)
            {
                case "monster":
                    _Monsters.Add(info);
                    row = MonsterList.Add();
                    Notebook.ActiveTab = 1;
                    break;

                case "special":
                    _Specials.Add(info);
                    row = SpecialList.Add();
                    Notebook.ActiveTab = 2;
                    break;

                case "item":
                case "loot":
                default:
                    _Items.Add(info);
                    row = ItemList.Add();
                    Notebook.ActiveTab = 0;
                    break;
            }
            
            // now add the item to the UI
            row[0][1] = Item.Icon + 0x6000000;
            row[1][0] = Item.Name;
            row[2][0] = info.Coords;

            if (_Config.CurrentOptions.Popup)
            {
                _MainView.Activate();
            }
            return true;
        }
        */

        public void PlaySound(string Sound)
        {
            if (_Config.CurrentOptions.Sound)
            {
                // TODO get the files on disk
                try
                {
                    SoundPlayer sp = new SoundPlayer(_Path + "\\" + Sound);
                    sp.Play();
                }
                catch (Exception) { }
            }
        }

        public void RemoveItem(int ItemID)
        {
            //First try to remove the ID from the Items list
            ObjectInfo FoundItem = _Items.FindById(ItemID);

            if (FoundItem != null)
            {
                int itemIndex = _Items.IndexOf(FoundItem);
                _Items.Remove(FoundItem);
                ItemList.Delete(itemIndex);
            }

            //Then try the Monsters list
            ObjectInfo FoundMonster = _Monsters.FindById(ItemID);

            if (FoundMonster != null)
            {
                int index = _Items.IndexOf(FoundMonster);
                _Monsters.Remove(FoundMonster);
                MonsterList.Delete(index);
            }

            // Finally the specials list
            ObjectInfo FoundSpecial = _Specials.FindById(ItemID);

            if (FoundSpecial != null)
            {
                int index = _Items.IndexOf(FoundSpecial);
                _Specials.Remove(FoundSpecial);
                SpecialList.Delete(index);
            }
        }

        private void RemoveDistantObjects()
        {
            int index = 0;

            foreach (ObjectInfo item in _Items)
            {
                double bDistance = Core.WorldFilter.Distance(PlayerObject.ID, item.ID, true);

                if (bDistance > _RemoveDistance)
                {
                    _Items.Delete(item.ID);
                    ItemList.Delete(index);
                }

                index++;
            }

            index = 0;
            foreach (ObjectInfo item in _Monsters)
            {
                double bDistance = Core.WorldFilter.Distance(PlayerObject.ID, item.ID, true);

                if (bDistance > 1)
                {
                    _Monsters.Delete(item.ID);
                    MonsterList.Delete(index);
                }

                index++;
            }

            index = 0;
            foreach (ObjectInfo item in _Specials)
            {
                double bDistance = Core.WorldFilter.Distance(PlayerObject.ID, item.ID, true);

                if (bDistance > 1)
                {
                    _Specials.Delete(item.ID);
                    SpecialList.Delete(index);
                }

                index++;
            }
        }
    }

     /*   
        struct QueueObject
        {
            int             ID;
            int             Value;
            MaterialInfo    Material;
            int             Landblock;
            float           xCoord;
            float           yCoord;
            int             Icon;
            string          Name;
        }

        private List<QueueObject> _ValueQueue;
        private List<QueueObject> _WorkmanshipQueue;
    }*/
}
